/*! ******************************************************************************
 *
 * Created on 2021年10月22日
 *
 * Copyright(c) YuZhou Big Data Laboratory CO.,Ltd, 2022.  All rights reserved.
 *
 *******************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************************/

package org.pentaho.di.ui.spoon.navigation.design;

import java.util.Timer;
import java.util.TimerTask;

import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;

/**
 * 具有淡入淡出效果且不需要用户点击关闭的消息提示框。
 * @author yzbdl@yzbdl.ac.cn
 *
 */
public class Notifier {
    private static int DISPLAY_TIME = 2000;

    private static final int FADE_TIMER = 10;

    private static final int FADE_IN_STEP = 30;

    private static final int FADE_OUT_STEP = 8;

    private static final int FINAL_ALPHA = 225;

    public static int DEFAULT_WIDTH = 250;

    public static int DEFAULT_HEIGHT = 140;

    private static Shell _oldShell;
    
    private static Color _bgFgGradient = new Color(null, 226, 239, 249);

    private static Color _bgBgGradient = new Color(null, 177, 211, 243);

    private static Color _borderColor = new Color(null, 177, 211, 243);

    public static void notify(Point point, String msg,Composite composite,int disableTime,int width,int height, boolean scrollable) {
        DISPLAY_TIME = disableTime;
        DEFAULT_WIDTH = width;
        DEFAULT_HEIGHT = height;
        if(msg.length()>130){
            msg = msg.substring(0,130)+"......";
        }

        final Shell parentShell = composite.getShell();
        final Shell newShell = new Shell(parentShell, SWT.NO_FOCUS | SWT.NO_TRIM);
        newShell.setLayout(new FillLayout());
        newShell.setBackgroundMode(SWT.INHERIT_FORCE);

        newShell.setLocation(point);
        
        composite.addDisposeListener(new DisposeListener() {

            public void widgetDisposed(DisposeEvent e) {

                newShell.dispose();

            }

        });
        final Composite inner = new Composite(newShell, SWT.NONE);
        FillLayout layout = new FillLayout();
        layout.marginWidth = 5;
        layout.marginHeight = 5;
        inner.setLayout(layout);

        newShell.addListener(SWT.Resize, new Listener() {
            public void handleEvent(Event event) {
                try {
                    Rectangle rect = newShell.getClientArea();
                    Image newImage = new Image(Display.getDefault(), Math.max(1, rect.width), rect.height);
                    GC gc = new GC(newImage);
                    // 背景
                    gc.setForeground(_bgFgGradient);
                    gc.setBackground(_bgBgGradient);
                    gc.fillGradientRectangle(rect.x, rect.y, rect.width, rect.height, true);
                    // 边框
                    gc.setLineWidth(1);
                    gc.setForeground(_borderColor);
                    gc.drawRectangle(rect.x , rect.y , rect.width - 2, rect.height - 2);

                    gc.dispose();
                    newShell.setBackgroundImage(newImage);
                    if (_oldShell != null) {
                        _oldShell.dispose();
                    }
                    _oldShell = newShell;
                } catch (Exception err) {
                    err.printStackTrace();
                }
            }
        });

        Label label = new Label(inner, SWT.WRAP | SWT.CENTER);
        label.setText(msg);
        label.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK));

        // 滚动开启关闭
        if( scrollable ) {
            Timer timer = new Timer(true);
            class myTask extends TimerTask {
                @Override
                public void run() {
                    Display.getDefault().syncExec(new Runnable() {
                        public void run() {
                            try {
                                int mx = label.getLocation().x;
                                int my = label.getLocation().y;
                                label.setLocation(mx, my - 1);
                            }catch (SWTException e){
                            }
                        }
                    });
                }
            }
            timer.schedule(new myTask(), 0, 100);
        }

        newShell.setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);

        if (Display.getDefault().getActiveShell() == null || Display.getDefault().getActiveShell().getMonitor() == null) {
            return;
        }
        newShell.setAlpha(0);
        newShell.setVisible(true);

        fadeIn(newShell);
    }

    private static void fadeIn(final Shell _shell) {
        Runnable run = new Runnable() {
            @Override
            public void run() {
                try {
                    if (_shell == null || _shell.isDisposed()) {
                        return;
                    }

                    int cur = _shell.getAlpha();
                    cur += FADE_IN_STEP;

                    if (cur > FINAL_ALPHA) {
                        _shell.setAlpha(FINAL_ALPHA);
                        startTimer(_shell);
                        return;
                    }

                    _shell.setAlpha(cur);
                    Display.getDefault().timerExec(FADE_TIMER, this);
                } catch (Exception err) {
                    err.printStackTrace();
                }
            }
        };
        Display.getDefault().timerExec(FADE_TIMER, run);
    }

    private static void startTimer(final Shell _shell) {
        Runnable run = new Runnable() {

            @Override
            public void run() {
                try {
                    if (_shell == null || _shell.isDisposed()) {
                        return;
                    }

                    fadeOut(_shell);
                } catch (Exception err) {
                    err.printStackTrace();
                }
            }

        };
        Display.getDefault().timerExec(DISPLAY_TIME, run);

    }

    private static void fadeOut(final Shell _shell) {
        final Runnable run = new Runnable() {

            @Override
            public void run() {
                try {
                    if (_shell == null || _shell.isDisposed()) {
                        return;
                    }

                    int cur = _shell.getAlpha();
                    cur -= FADE_OUT_STEP;

                    if (cur <= 0) {
                        _shell.setAlpha(0);
                        if (_oldShell != null) {
                            _oldShell.dispose();
                        }
                        _shell.dispose();
                        return;
                    }

                    _shell.setAlpha(cur);

                    Display.getDefault().timerExec(FADE_TIMER, this);

                } catch (Exception err) {
                    err.printStackTrace();
                }
            }

        };
        Display.getDefault().timerExec(FADE_TIMER, run);

    }
}